package com.sbtr.business.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sbtr.business.auth.service.impl.RoleServiceImpl;
import com.sbtr.business.classify.service.impl.AlgorithmInfoServiceImpl;
import com.sbtr.business.material.service.impl.MaterialInfoServiceImpl;
import com.sbtr.business.project.entity.Project;
import com.sbtr.business.project.mapper.ProjectMapper;
import com.sbtr.business.project.service.IProjectService;
import com.sbtr.business.trainingmodel.entity.TrainingModelData;
import com.sbtr.business.trainingmodel.mapper.TrainingModelDataMapper;
import com.sbtr.business.trainingmodel.service.ITrainingModelDataService;
import com.sbtr.business.trainingmodel.service.impl.TrainingModelDataServiceImpl;
import com.sbtr.business.trainingtask.mapper.TrainingInfoMapper;
import com.sbtr.business.trainingtask.service.impl.TrainingInfoServiceImpl;
import com.sbtr.common.PageDto;
import com.sbtr.constant.ColumnConstant;
import com.sbtr.constant.ProjectConstant;
import com.sbtr.open.project.dto.ProjectDto;
import com.sbtr.open.project.dto.ProjectModelDto;
import com.sbtr.open.project.dto.ProjectSearchDto;
import com.sbtr.open.trainingmodel.dto.ModelCountDto;
import com.sbtr.open.trainingmodel.dto.TrainingModelDataDto;
import com.sbtr.open.trainingtask.dto.TrainingInfoDto;
import com.sbtr.overview.dto.AllCountDto;
import com.sbtr.overview.dto.MaterialSetTypeCountDto;
import com.sbtr.overview.dto.ModelTypeCountDto;
import com.sbtr.overview.dto.ProjectRateCountDto;
import com.sbtr.util.BeanCopyUtils;
import com.sbtr.util.PageDtoUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 图像识别项目表 服务实现类
 * </p>
 */
@Transactional
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    private Logger logger = LoggerFactory.getLogger(ProjectServiceImpl.class);
    private static final String[] NOR_TYPE = {ProjectConstant.PROJECT_TYPE_IMG_DETECTION, ProjectConstant.PROJECT_TYPE_IMG_CLASSIFY, ProjectConstant.PROJECT_TYPE_DATA_PREDICT, ProjectConstant.PROJECT_TYPE_VOICE_CLASSIFY, ProjectConstant.PROJECT_TYPE_TXT_CLASSIFY, ProjectConstant.PROJECT_TYPE_IMG_SEGMENT};
    private static final String[] SPEC_TYPE = {ProjectConstant.PROJECT_TYPE_IMG_SLICING};
    @Autowired
    private RoleServiceImpl roleService;
    @Autowired
    private TrainingModelDataServiceImpl trainingModelDataService;
    @Resource
    private TrainingModelDataMapper trainingModelDataMapper;
    @Autowired
    private MaterialInfoServiceImpl materialInfoService;

    @Autowired
    private AlgorithmInfoServiceImpl AlgorithmInfoService;

    @Autowired
    private TrainingInfoServiceImpl trainingInfoService;

    @Resource
	TrainingInfoMapper trainingInfoMapper;

    @Override
    public AllCountDto getAllCount(String creater) {
        AllCountDto allCountDto = baseMapper.projectCount(creater);
        AllCountDto allCountDto1 = trainingModelDataService.modelCount(creater);
        AllCountDto allCountDto2 = materialInfoService.materialCount(creater);
        allCountDto.setModelCount(allCountDto1.getModelCount());
        allCountDto.setMaterialCount(allCountDto2.getMaterialCount());
        return allCountDto;
    }

    @Override
    public List<ProjectRateCountDto> getProjectRateCount(String creater) {
        List<ProjectRateCountDto> projectRateCount = baseMapper.projectRateCount(creater);
        return projectRateCount;
    }

    @Override
    public List<ModelTypeCountDto> getModelTypeCount(String creater) {
        List<ModelTypeCountDto> modelTypeCount = trainingModelDataService.modelTypeCount(creater);
        return modelTypeCount;
    }

    @Override
    public List<MaterialSetTypeCountDto> getMaterialSetTypeCount(String creater) {
        List<MaterialSetTypeCountDto> materialSetTypeCountDto = materialInfoService.materialSetTypeCount(creater);
        return materialSetTypeCountDto;
    }

    @Override
    public boolean batchDeleteById(List<Long> idList) {
        for (Long id : idList) {
            Project project = baseMapper.selectById(id);
            // 只有创建者或者管理员有权限删除素材集
            Assert.isTrue(project != null && StringUtils.isNotBlank(project.getStatus())
                    && !ProjectConstant.PROJECT_STATUS_PUBLISHED.equals(project.getStatus()), "已发布项目不允许删除");
//			Assert.isTrue((project != null && project.getCreater().equalsIgnoreCase(UserUtils.getFdLoginName()))
//					|| roleService.isAdmin(UserUtils.getFdLoginName()), "权限不足");
            baseMapper.updateIsAvailableById(id);
        }
        return true;
    }

    @Override
    public PageDto<ProjectDto> searchPage(ProjectSearchDto pro) {
        IPage<ProjectDto> page = new Page<>();
        page.setSize(pro.getPageSize());
        page.setCurrent(pro.getPage());
        QueryWrapper<ProjectDto> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.PROJECT_IS_AVAILABLE, 1);
        if (null != pro.getId()) {
            wrapper.like(ColumnConstant.PROJECT_ID, pro.getId());
        }
        if (StringUtils.isNotEmpty(pro.getProjectName())) {
            wrapper.like(ColumnConstant.PROJECT_NAME, pro.getProjectName());
        }
        if (StringUtils.isNotEmpty(pro.getProjectDesc())) {
            wrapper.like(ColumnConstant.PROJECT_DESC, pro.getProjectDesc());
        }
        if (StringUtils.isNotEmpty(pro.getCreater()) && !roleService.isAdmin(pro.getCreater())) {
            wrapper.eq(ColumnConstant.PROJECT_CREATER, pro.getCreater());
        }
        if (StringUtils.isNotBlank(pro.getBelonger())) {
            wrapper.and(e->{
                e.eq("p.belonger",pro.getBelonger()).or().isNull("p.belonger");
            });
        }

//		if(null != pro.getAriType() && pro.getAriType() != 0) {
//			if(pro.getAriType()==1 && null != pro.getTypes() && !pro.getTypes().isEmpty()) {
//				wrapper.in(ColumnConstant.PROJECT_TYPE, pro.getTypes());
//			} else {
//				wrapper.in(ColumnConstant.PROJECT_TYPE, Arrays.asList(SPEC_TYPE));
//			}
//		} else {
//			if( null != pro.getTypes() && !pro.getTypes().isEmpty()) {
//				wrapper.in(ColumnConstant.PROJECT_TYPE, pro.getTypes());
//			} else {
//				wrapper.in(ColumnConstant.PROJECT_TYPE, Arrays.asList(NOR_TYPE));
//			}
//		}

        if (null != pro.getRates() && !pro.getRates().isEmpty()) {
            wrapper.in(ColumnConstant.PROGRESS_RATE, pro.getRates());
        }

        if (null != pro.getStatus() && !pro.getStatus().isEmpty()) {
            wrapper.in("p.status", pro.getStatus());
        }

        if (StringUtils.isNotEmpty(pro.getMaterialSetName())) {
            wrapper.like(ColumnConstant.FILE_NAME, pro.getMaterialSetName());
        }
        if (null != pro.getTypes() && !pro.getTypes().isEmpty()) {
            wrapper.in(ColumnConstant.PROJECT_TYPE, pro.getTypes());
        }

        if (null != pro.getDiagnoseType() && pro.getDiagnoseType()!=0) {
            wrapper.eq("diagnose_type", pro.getDiagnoseType());
        }

    /*    Set<String> types = new HashSet<>();
        types.add("1001");
        types.add("1006");
        types.add("1007");
        String type = "故障预测";
        if (types.contains(trainingModelDataDto.getType())) {
            type = "故障诊断";
        }*/


        wrapper.orderByDesc("p.id");
//		page = page(page, wrapper);
        page = baseMapper.customPage(page, wrapper);
        PageDto<ProjectDto> pageDto = PageDtoUtils.getPageDtoByIPage(page, ProjectDto.class);
//		setModelCount(pageDto.getList());
        return pageDto;
    }

    @Override
    public List<String> getProjectType() {
        return AlgorithmInfoService.getProjectType();
    }

    @Override
    public List<String> getAlgorithmName() {
        return AlgorithmInfoService.getAlgorithmName();
    }


    @Override
    public ProjectDto findById(Long id) {

        //多个算法执行情况
        //查询结果数据
        QueryWrapper<TrainingModelData> wrapper2 = new QueryWrapper<>();
        wrapper2.eq("project_id", id);
        wrapper2.orderByDesc("create_time");
		List<TrainingModelData>  list2 = trainingModelDataService.list(wrapper2);
        //查询算法类型
        TrainingInfoDto trainingInfoDto = trainingInfoService.getByProjectId(id);
		if(trainingInfoDto!=null){
            String type = trainingInfoDto.getType();
            //taskId，taskDataId
            Map<Long,Long> delIds = new HashMap<>();
            if (list2 != null && !list2.isEmpty()) {
                if (list2.size() > 1) {
                    TrainingModelData trainingModelData = trainingModelDataService.compareBest(type, list2);
                    for (TrainingModelData trainingModelData1:list2) {
                        if(!trainingModelData1.getId().equals(trainingModelData.getId())){
                            delIds.put(trainingModelData1.getTaskId(),trainingModelData1.getId());
                        }
                    }
                    trainingInfoMapper.deleteBatchIds(delIds.keySet());
                    trainingModelDataMapper.deleteBatchIds(delIds.values());
                }
            }
        }

        ProjectDto dto = BeanCopyUtils.copyProperties(getById(id), ProjectDto.class);
        // 查询该项目的模型数量
        List<ModelCountDto> modelCountByProject = trainingModelDataService.modelCountByProject(Arrays.asList(dto.getId()));
        if (modelCountByProject != null && !modelCountByProject.isEmpty()) {
            for (ModelCountDto modelCountDto : modelCountByProject) {
                if (dto.getId().equals(modelCountDto.getProjectId())) {
                    dto.setModelCount(modelCountDto.getCount());
                    break;
                }
            }
        }
        return dto;
    }

    @Override
    public boolean deleteById(Long id) {
        Project project = baseMapper.selectById(id);
        // 只有创建者或者管理员有权限删除素材集
        Assert.isTrue(project != null && StringUtils.isNotBlank(project.getStatus())
                && !ProjectConstant.PROJECT_STATUS_PUBLISHED.equals(project.getStatus()), "已发布项目不允许删除");
        Assert.isTrue((
                project != null && project.getCreater() != null
//						equalsIgnoreCase(UserUtils.getFdLoginName()))
//				|| roleService.isAdmin(UserUtils.getFdLoginName()
        ), "权限不足")
        ;
        baseMapper.updateIsAvailableById(id);
        return true;
    }


    @Override
    public ProjectDto save(ProjectDto dto) {
        Project project = BeanCopyUtils.copyProperties(dto, Project.class);
        Assert.isTrue(StringUtils.isNotBlank(project.getProjectDesc()) ,
                "模型描述不能为空");
//        Assert.isTrue(StringUtils.isBlank(project.getProjectDesc()) && project.getProjectDesc().length() > 400,
//                "数据集描述不能为空");

        if (dto.getId() == null) {
            QueryWrapper<Project> wrapper = new QueryWrapper<>();
            wrapper.eq(ColumnConstant.PROJECT_NAME, dto.getProjectName());
            wrapper.eq("diagnose_type", dto.getDiagnoseType());
            if (StringUtils.isNotEmpty(dto.getCreater())) {
                wrapper.eq(ColumnConstant.CREATER, dto.getCreater());
            }
            wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
            Assert.isTrue(this.count(wrapper) == 0, "项目名称已存在");
            // 新建默认进度是导入素材
            if (!dto.getProjectType().equals("other")) {
                project.setProgressRate(ProjectConstant.PROJECT_PROGRESS_MATERIAL);
                dto.setProgressRate(ProjectConstant.PROJECT_PROGRESS_MATERIAL);
                project.setStatus(ProjectConstant.PROJECT_STATUS_UNPUBLISH);
                dto.setStatus(ProjectConstant.PROJECT_STATUS_UNPUBLISH);
            }
            project.setIsAvailable(true);
            dto.setIsAvailable(true);
            project.setAppId("IMG" + System.currentTimeMillis() + (new Random().nextInt(100)));
            project.setAppKey(UUID.randomUUID().toString().replace("-", ""));
            logger.info("新增项目：{}", dto.getProjectName());
            save(project);
        } else {
            QueryWrapper<Project> wrapper = new QueryWrapper<>();
            wrapper.eq(ColumnConstant.PROJECT_NAME, dto.getProjectName());
            wrapper.eq("diagnose_type", dto.getDiagnoseType());
            if (StringUtils.isNotEmpty(dto.getCreater())) {
                wrapper.eq(ColumnConstant.CREATER, dto.getCreater());
            }
            wrapper.ne("id", dto.getId());
            wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
            Assert.isTrue(this.count(wrapper) == 0, "项目名称已存在");
            logger.info("修改项目：{}", dto.getProjectName());
            updateById(project);
        }
        dto.setId(project.getId());
        return dto;
    }

    @Override
    public ProjectDto saveFileId(ProjectDto dto) {
        Project data = BeanCopyUtils.copyProperties(dto, Project.class);
        updateById(data);
        dto.setId(data.getId());
        return dto;

//		Project oldProject = getById(dto.getId());
//		if (oldProject.getFileId() == null){//项目无素材
//			updateById(data);
//			oldProject.setFileId(dto.getFileId());
//		}else {//项目已有素材
//			oldProject.setFileId(dto.getFileId());
//			oldProject.setId(null);
//			save(oldProject);
//		}
//		return BeanCopyUtils.copyProperties(oldProject, ProjectDto.class);

    }

    @Override
    public ProjectDto update(ProjectDto dto) {
        Project project = BeanCopyUtils.copyProperties(dto, Project.class);
        Assert.isTrue(StringUtils.isNotBlank(project.getProjectDesc()) && project.getProjectDesc().length() < 400,
                "项目描述过长");
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.PROJECT_NAME, dto.getProjectName());
        if (StringUtils.isNotEmpty(dto.getCreater())) {
            wrapper.eq(ColumnConstant.CREATER, dto.getCreater());
        }
        wrapper.ne("id", dto.getId());
        wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
        Assert.isTrue(this.count(wrapper) == 0, "项目名称已存在");
        logger.info("修改项目：{}", dto.getProjectName());
        updateById(project);
        dto.setId(project.getId());
        return dto;
    }


    @Override
    public void updateProject(Long projectId, String status) {
        Project project = new Project();
        project.setId(projectId);
        project.setProgressRate(status);
        updateById(project);
    }

    @Override
    public List<ProjectDto> getProjectList(String creater) {
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.CREATER, creater).orderByDesc(ColumnConstant.CREATER);
        wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
        return BeanCopyUtils.copyProperties(list(wrapper), ProjectDto.class);
    }

    @Override
    public List<ProjectDto> getProjectListAdmin(String userId) {
        boolean isAdmin = roleService.isAdmin(userId);
        if (isAdmin) {
            QueryWrapper<Project> wrapper = new QueryWrapper<>();
            wrapper.isNotNull(ColumnConstant.CREATER);
            return BeanCopyUtils.copyProperties(list(wrapper), ProjectDto.class);
        } else {
            QueryWrapper<Project> wrapper = new QueryWrapper<>();
            wrapper.eq(ColumnConstant.CREATER, userId).orderByDesc(ColumnConstant.CREATER);
            wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
            return BeanCopyUtils.copyProperties(list(wrapper), ProjectDto.class);
        }

    }

    @Override
    public ProjectDto findByAppId(String appId) {
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.APPID, appId);
        wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
        wrapper.last("LIMIT 1");
        return BeanCopyUtils.copyProperties(getOne(wrapper), ProjectDto.class);
    }

    @Override
    public PageDto<ProjectDto> searchByCreater(ProjectSearchDto pro) {
        IPage<Project> page = new Page<>();
        page.setSize(pro.getPageSize());
        page.setCurrent(pro.getPage());
        QueryWrapper<Project> wrapper = new QueryWrapper<>();
        wrapper.eq(ColumnConstant.IS_AVAILABLE, 1);
        if (StringUtils.isNotEmpty(pro.getProjectName())) {
            wrapper.like(ColumnConstant.PROJECT_NAME, pro.getProjectName());
        }
        if (StringUtils.isNotBlank(pro.getCreater())) {
            wrapper.eq(ColumnConstant.CREATER, pro.getCreater());
        }
        if (null != pro.getTypes() && !pro.getTypes().isEmpty()) {
            wrapper.in(ColumnConstant.PROJECT_TYPE, pro.getTypes());
        }
        if (null != pro.getRates() && !pro.getRates().isEmpty()) {
            wrapper.in(ColumnConstant.PROGRESS_RATE, pro.getRates());
        }
        if (null != pro.getStatus() && !pro.getStatus().isEmpty()) {
            wrapper.in(ColumnConstant.STATUS, pro.getStatus());
        }
        wrapper.orderByDesc("id");
        page = page(page, wrapper);
        PageDto<ProjectDto> pageDto = PageDtoUtils.getPageDtoByIPage(page, ProjectDto.class);
//		setModelCount(pageDto.getList());
        return pageDto;
    }

    @Override
    public List<ProjectModelDto> searchModelByUserId(String userId) {
        return baseMapper.searchModelByUserId(userId);
    }
}
